package com.miraclesea.test.database.module;

import org.dbunit.database.IMetadataHandler;
import org.dbunit.dataset.datatype.DefaultDataTypeFactory;
import org.dbunit.ext.db2.Db2DataTypeFactory;
import org.dbunit.ext.db2.Db2MetadataHandler;
import org.dbunit.ext.h2.H2DataTypeFactory;
import org.dbunit.ext.hsqldb.HsqldbDataTypeFactory;
import org.dbunit.ext.mckoi.MckoiDataTypeFactory;
import org.dbunit.ext.mssql.MsSqlDataTypeFactory;
import org.dbunit.ext.mysql.MySqlDataTypeFactory;
import org.dbunit.ext.mysql.MySqlMetadataHandler;
import org.dbunit.ext.netezza.NetezzaDataTypeFactory;
import org.dbunit.ext.netezza.NetezzaMetadataHandler;
import org.dbunit.ext.oracle.Oracle10DataTypeFactory;
import org.dbunit.ext.oracle.OracleDataTypeFactory;
import org.dbunit.ext.postgresql.PostgresqlDataTypeFactory;
import org.unitils.core.UnitilsException;

public enum SupportedDatabaseType {
	
	Db2(Db2DataTypeFactory.class, Db2MetadataHandler.class), 
	H2(H2DataTypeFactory.class), 
	Hsqldb(HsqldbDataTypeFactory.class), 
	Mckoi(MckoiDataTypeFactory.class), 
	MsSql(MsSqlDataTypeFactory.class), 
	MySql(MySqlDataTypeFactory.class, MySqlMetadataHandler.class), 
	Netezza(NetezzaDataTypeFactory.class, NetezzaMetadataHandler.class), 
	Oracle(OracleDataTypeFactory.class), 
	Oracle10(Oracle10DataTypeFactory.class), 
	Postgresql(PostgresqlDataTypeFactory.class);
	
	private final Class<? extends DefaultDataTypeFactory> dataTypeFactoryClass;
	private final Class<? extends IMetadataHandler> metadataHandlerClass;
	
	private SupportedDatabaseType(final Class<? extends DefaultDataTypeFactory> dataTypeFactoryClass, final Class<? extends IMetadataHandler> metadataHandlerClass) {
		this.dataTypeFactoryClass = dataTypeFactoryClass;
		this.metadataHandlerClass = metadataHandlerClass;
	}
	
	private SupportedDatabaseType(final Class<? extends DefaultDataTypeFactory> dataTypeFactoryClass) {
		this(dataTypeFactoryClass, null);
	}

	public DefaultDataTypeFactory getDataTypeFactory() {
		return newInstance(dataTypeFactoryClass);
	}


	public IMetadataHandler getMetadataHandler() {
		if (null == metadataHandlerClass) {
			return null;
		}
		return newInstance(metadataHandlerClass);
	}
	
	private <T> T newInstance(final Class<T> clazz) {
		try {
			return clazz.newInstance();
		} catch (final InstantiationException ex) {
			throw new UnitilsException(String.format("Cannot Instantiation class '%s'", clazz.getName()), ex);
		} catch (final IllegalAccessException ex) {
			throw new UnitilsException(String.format("Illegal access for class '%s'", clazz.getName()), ex);
		}
	}
	
}
